package com.example.designpattern.responsibility;

import com.example.model.GoodsDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;


/**
 * 总结
 *
 * 1：模板模式   在父类定义执行顺序，公共方法，个性化的东西交给子类实现
 * 2：责任链模式  构建调用链路，节点中维护下一个节点的引用，像火炬一样传递下去
 * 3：单一职责原则  当前可以在一个类一个方法完成所有的校验逻辑，但是太臃肿，责任链可以实现功能解耦
 * 4：开闭原则 如果需要再新增一个校验点，只需要实现这个父类，重写几个方法就好了，不需要动原来的业务逻辑
 *
 * @author long
 * @date 2024/4/20 11:18
 */
public abstract class AbstractValidator implements IValidator {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 下一个节点
     */
    protected IValidator next;

    @Override
    public IValidator setNext(IValidator next) {
        this.next = next;
        return next;
    }

    @Override
    public void validate(GoodsDTO dto) {

        // 前置处理
        preValidate(dto);

        // 真正的校验逻辑
        doValidate(dto);

        // 后置处理
        postValidate(dto);

        // 如果下一个校验器不为空，则传递给下一个节点
        if(next != null){
            next.validate(dto);
        }
    }

    /**
     * 校验前置处理
     */
    protected void preValidate(GoodsDTO dto){

    }

    /**
     * 真正的校验逻辑交给子类实现 for subClass
     * @param dto
     */
    protected abstract void doValidate(GoodsDTO dto);

    /**
     * 校验后置处理
     */
    protected void postValidate(GoodsDTO dto){

    }

    /**
     * 这里不能使用afterPropertiesSet，有可能ApplicationUtils对象还没有实例化
     */
    @Override
    public void afterSingletonsInstantiated() {
        // 初始化bean的下一个节点对象
        if(Objects.isNull(next)){
            this.next = getNextNode();
        }
    }

}
